// Copyright 2018 The OpenPitrix Authors. All rights reserved.
// Use of this source code is governed by a Apache license
// that can be found in the LICENSE file.

// +build ignore

//go:generate go run gen_helper.go
//go:generate go fmt ./...

package main

import (
	"html/template"
	"log"
	"os"

	"openpitrix.io/openpitrix/pkg/util/stringutil"
)

var syncTemplate = template.Must(template.New("").Funcs(template.FuncMap{
	"snakeCase":  stringutil.CamelCaseToUnderscore,
	"pascalCase": stringutil.UnderscoreToCamelCase,
}).Parse(`
func Sync{{pascalCase .Name}}{{pascalCase .Key}}s(ctx context.Context, {{.Name}}Id, {{.Key}}Str string) error {
	{{.Key}}Query, err := Parse({{.Key}}Str)
	if err != nil {
		return gerr.NewWithDetail(ctx, gerr.InvalidArgument, err, gerr.ErrorParameterParseFailed, "{{.Key}}")
	}
	var {{.Key}}s []*models.{{pascalCase .Name}}{{pascalCase .Key}}
	_, err = pi.Global().DB(ctx).
		Select(models.{{pascalCase .Name}}{{pascalCase .Key}}Columns...).
		From(constants.Table{{pascalCase .Name}}{{pascalCase .Key}}).
		Where(db.Eq(constants.Column{{pascalCase .Name}}Id, {{.Name}}Id)).
		OrderDir(constants.ColumnCreateTime, true).
		Load(&{{.Key}}s)
	if err != nil {
		return gerr.NewWithDetail(ctx, gerr.InvalidArgument, err, gerr.ErrorDescribeResourcesFailed)
	}
	i := 0
	// update exists {{.Key}}
	// insert new {{.Key}}
	// delete outmoded {{.Key}}
	insert := pi.Global().DB(ctx).InsertInto(constants.Table{{pascalCase .Name}}{{pascalCase .Key}})
	for _, q := range {{.Key}}Query {
		if len({{.Key}}s) >= i+1 {
            {{.Key}} := {{.Key}}s[i]
            if {{.Key}}.{{pascalCase .Key}}Key != q.K || {{.Key}}.{{pascalCase .Key}}Value != q.V {
                _, err = pi.Global().DB(ctx).
                    Update(constants.Table{{pascalCase .Name}}{{pascalCase .Key}}).
                    Set(constants.Column{{pascalCase .Key}}Key, q.K).
                    Set(constants.Column{{pascalCase .Key}}Value, q.V).
                    Where(db.Eq(constants.Column{{pascalCase .Name}}{{pascalCase .Key}}Id, {{.Key}}.{{pascalCase .Name}}{{pascalCase .Key}}Id)).
                    Exec()
                if err != nil {
                    return gerr.NewWithDetail(ctx, gerr.Internal, err, gerr.ErrorModifyResourcesFailed)
                }
            }
        } else {
            repo{{pascalCase .Key}} := models.New{{pascalCase .Name}}{{pascalCase .Key}}({{.Name}}Id, q.K, q.V)
            insert = insert.Record(repo{{pascalCase .Key}})
        }
        i++
	}
	if len(insert.Value) > 0 {
		_, err = insert.Exec()
		if err != nil {
			return gerr.NewWithDetail(ctx, gerr.Internal, err, gerr.ErrorModifyResourcesFailed)
		}
	}
	if len({{.Key}}s) >= i+1 {
		var delete{{pascalCase .Key}}Ids []string
		{{.Key}}s = {{.Key}}s[i:]
		for _, {{.Key}} := range {{.Key}}s {
			delete{{pascalCase .Key}}Ids = append(delete{{pascalCase .Key}}Ids, {{.Key}}.{{pascalCase .Name}}{{pascalCase .Key}}Id)
		}
		_, err := pi.Global().DB(ctx).
			DeleteFrom(constants.Table{{pascalCase .Name}}{{pascalCase .Key}}).
			Where(db.Eq(constants.Column{{pascalCase .Name}}{{pascalCase .Key}}Id, delete{{pascalCase .Key}}Ids)).
			Exec()
		if err != nil {
			return gerr.NewWithDetail(ctx, gerr.Internal, err, gerr.ErrorModifyResourcesFailed)
		}
	}
	return err
}
`))

type Model struct {
	Name string
	Key  string
}

func main() {
	f, err := os.Create("sync.go")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	f.Write([]byte(`// Copyright 2018 The OpenPitrix Authors. All rights reserved.
// Use of this source code is governed by a Apache license
// that can be found in the LICENSE file.

// Auto generated by 'go run gen_helper.go', DO NOT EDIT.

package labelutil

import (
	"context"

	"openpitrix.io/openpitrix/pkg/constants"
	"openpitrix.io/openpitrix/pkg/db"
	"openpitrix.io/openpitrix/pkg/gerr"
	"openpitrix.io/openpitrix/pkg/models"
	"openpitrix.io/openpitrix/pkg/pi"
)
`))

	var models = []Model{
		{"repo", "label"},
		{"repo", "selector"},
	}

	for _, m := range models {
		syncTemplate.Execute(f, m)
	}
}
